using System.Collections.Generic;
using System.Linq;
using WebAuth.Bussiness;
using WebAuth.DAO;

/***
 * 用于实现用户和具体权限项的直接映射。
 */
namespace WebAuth.Models
{
    public class AuthItemsMap : Dictionary<string, AuthItem>
    {
        private volatile uint _cacheVersion;
        private object locker = new object();

        public string Userid { get; }

        public AuthItemsMap(string userid)
        {
            Userid = userid;
        }


        public uint GetCacheVersion()
        {
            lock (locker)
            {
                return _cacheVersion;
            }
        }

        public int LoadAuthItems(string userid)
        {
            var dbContext = DbManager.GetDbContext();

            lock (locker)
            {
                var cachManager = CacheManager.GetCacheManager();
                _cacheVersion = cachManager.GetCachVersion();
                cachManager.GetModelById(userid, out User userModel);
                
                Clear();
                foreach (var authBinder in userModel.AuthChildren)
                {
                    if (authBinder is AuthBinder binder)
                    {
                        //Get directly assigned role/department binder's authitems
                        GetAuthItemsFromBinder(binder);

                        //Get derived authitems from department upcast/downcast
                        var deriveBinders = dbContext.AuthBinders.Where(b =>
                            b.Role == binder.Role && b.Id != binder.Id &&
                            !string.IsNullOrEmpty(binder.Derive));
                        foreach (var deriveBinder in deriveBinders)
                        {
                            var deriveDepartments = deriveBinder.GetDeriveDepartments();
                            if (deriveDepartments.Contains(binder.Department))
                            {
                                GetAuthItemsFromBinder(deriveBinder);
                            }
                        }
                    }
                }

            }

            void GetAuthItemsFromBinder(AuthBinder binder)
            {
                foreach (var authGroup in binder.AuthChildren)
                {
                    if (authGroup is AuthGroup group)
                    {
                        foreach (var authItem in group.AuthChildren)
                        {
                            if (authItem is AuthItem item)
                            {
                                if (!ContainsKey(item.Id))
                                {
                                    Add(item.Id, item);
                                }
                            }
                        }
                    }
                }
            }

            /*
            void GetAuthItemsFromBinder(AuthBinder binder)
            {
                foreach (var authGroup in binder.AuthChildren)
                {
                    if (authGroup is AuthGroup group)
                    {
                        foreach (var authItem in group.AuthChildren)
                        {
                            if (authItem is AuthItem item)
                            {
                                if (!ContainsKey(item.Id))
                                {
                                    Add(item.Id, item);
                                }
                            }
                        }
                    }
                }
            }
            */

            return this.Count;
        }
    }
}